home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / sync / syncUser.c < prev   
C/C++ Source or Header  |  1991-03-23  |  7KB  |  247 lines

  1. /* 
  2.  * syncUser.c --
  3.  *
  4.  *    These are system call routines of the Synchronization module that
  5.  *    support monitors for user-level code.
  6.  *
  7.  *    A process is blocked by making it wait on an event.  An event is
  8.  *    just an uninterpreted integer that gets 'signaled' by the routine
  9.  *    Sync_UserSlowBroadcast.
  10.  *    
  11.  *    We pin a user's page into memory before touching it.  This
  12.  *    simplifies locking and lets us hold the sched master lock
  13.  *    while touching user memory.  
  14.  *    
  15.  *    The calls to Vm_MakeAccessible are assumed to succeed because
  16.  *    the calls to Vm_PinUserMemory succeeded.  The calls to 
  17.  *    Vm_MakeAccessible come before obtaining the sched master lock; 
  18.  *    this shouldn't matter for native Sprite (Vm_MakeAccessible 
  19.  *    shouldn't block), but it could make a difference for the
  20.  *    Sprite server (on Mach).  The locks set by Vm_MakeAccessible
  21.  *    should not be held while waiting for an event.
  22.  *
  23.  * Copyright 1986, 1991 Regents of the University of California
  24.  * All rights reserved.
  25.  */
  26.  
  27. #ifndef lint
  28. static char rcsid[] = "$Header: /sprite/src/kernel/sync/RCS/syncUser.c,v 9.4 91/03/17 20:52:18 kupfer Exp $ SPRITE (Berkeley)";
  29. #endif /* not lint */
  30.  
  31. #include <sprite.h>
  32. #include <mach.h>
  33. #include <sync.h>
  34. #include <syncInt.h>
  35. #include <sched.h>
  36. #include <sys.h>
  37. #include <vm.h>
  38.  
  39.  
  40. /*
  41.  * ----------------------------------------------------------------------------
  42.  *
  43.  * Sync_SlowLockStub --
  44.  *
  45.  *    Stub for the Sync_SlowLock system call.
  46.  *    Acquire a lock while holding the synchronization master lock.
  47.  *
  48.  *      Inside the critical section the inUse bit is checked.  If we have
  49.  *      to wait the process is put to sleep waiting on an event associated
  50.  *      with the lock.
  51.  *
  52.  * Results:
  53.  *    None.
  54.  *
  55.  * Side effects:
  56.  *      The lock is acquired when this procedure returns.  The process may
  57.  *      have been put to sleep while waiting for the lock to become
  58.  *      available.
  59.  *
  60.  * ----------------------------------------------------------------------------
  61.  */
  62.  
  63. ReturnStatus
  64. Sync_SlowLockStub(lockPtr)
  65.     Sync_UserLock *lockPtr;
  66. {
  67.     ReturnStatus    status = SUCCESS;
  68.     Proc_ControlBlock    *procPtr;
  69.     Sync_UserLock    *userLockPtr; /* lock's addr in kernel addr space */
  70.     int            numBytes; /* number of bytes accessible */
  71.     Boolean        waiting = TRUE;
  72.  
  73.     procPtr = Proc_GetCurrentProc();
  74.  
  75.     status = Vm_PinUserMem(VM_READWRITE_ACCESS, sizeof(*lockPtr),
  76.             (Address)lockPtr);
  77.     if (status != SUCCESS) {
  78.     return(status);
  79.     }
  80.  
  81.     while (waiting) {
  82.     Vm_MakeAccessible(VM_READWRITE_ACCESS, sizeof(*lockPtr),
  83.               (Address)lockPtr, &numBytes,
  84.               (Address *)&userLockPtr);
  85.     MASTER_LOCK(sched_MutexPtr);
  86.     waiting = (Mach_TestAndSet(&(userLockPtr->inUse)) != 0);
  87.     if (waiting) {
  88.         userLockPtr->waiting = TRUE;
  89.     }
  90.     Vm_MakeUnaccessible((Address)userLockPtr, numBytes);
  91.     if (!waiting) {
  92.         break;
  93.     }
  94.  
  95.     (void) SyncEventWaitInt((unsigned int)lockPtr, TRUE);
  96. #ifdef spur
  97.     Mach_InstCountEnd(1);
  98. #endif
  99.     MASTER_UNLOCK(sched_MutexPtr);
  100.     MASTER_LOCK(sched_MutexPtr);
  101.     if (Sig_Pending(procPtr)) {
  102.         status = GEN_ABORTED_BY_SIGNAL;
  103.         break;
  104.     }
  105.     MASTER_UNLOCK(sched_MutexPtr);
  106.     }
  107. #ifdef spur
  108.     if (Mach_InstCountIsOn(1)) {
  109.     panic("About to unlock sched_Mutex with inst count on.\n");
  110.     }
  111. #endif
  112.  
  113.     /* 
  114.      * We always exit the loop holding the sched master lock.
  115.      */
  116.     MASTER_UNLOCK(sched_MutexPtr);
  117.  
  118.     (void)Vm_UnpinUserMem(sizeof(*lockPtr), (Address)lockPtr);
  119.     return(status);
  120. }
  121.  
  122.  
  123. /*
  124.  * ----------------------------------------------------------------------------
  125.  *
  126.  * Sync_SlowWaitStub --
  127.  *
  128.  *    Stub for the Sync_SlowWait system call.
  129.  *      Wait on an event.  The lock is released and the process is blocked
  130.  *      on the event.  A future call to Sync_UserSlowBroadcast will signal the
  131.  *      event and make this process runnable again.
  132.  *
  133.  *      This can only be called while a lock is held.  This forces our
  134.  *      client to safely check global state while in a monitor.  The 
  135.  *      caller of this system call (i.e., the Sync_SlowWait library
  136.  *      routine) must reacquire the lock before returning.
  137.  *
  138.  * Results:
  139.  *    None.
  140.  *
  141.  * Side effects:
  142.  *      Put the process to sleep and release the monitor lock.  Other
  143.  *      processes waiting on the monitor lock become runnable.
  144.  *    
  145.  *
  146.  * ----------------------------------------------------------------------------
  147.  */
  148. ReturnStatus
  149. Sync_SlowWaitStub(event, lockPtr, wakeIfSignal)
  150.     unsigned     int     event;
  151.     Sync_UserLock    *lockPtr;
  152.     Boolean        wakeIfSignal;
  153. {
  154.     ReturnStatus    status;
  155.     Sync_UserLock     *userLockPtr; /* lock's addr in kernel addr space */
  156.     int            numBytes; /* number of bytes accessible */
  157.  
  158.     status = Vm_PinUserMem(VM_READWRITE_ACCESS, sizeof(*lockPtr),
  159.             (Address)lockPtr);
  160.     if (status != SUCCESS) {
  161.     return(status);
  162.     }
  163.  
  164.     Vm_MakeAccessible(VM_READWRITE_ACCESS, sizeof(*lockPtr),
  165.               (Address)lockPtr, &numBytes,
  166.               (Address *)&userLockPtr);
  167.     MASTER_LOCK(sched_MutexPtr);
  168.     /*
  169.      * release the monitor lock and wait on the condition
  170.      */
  171.     userLockPtr->inUse = 0;
  172.     userLockPtr->waiting = FALSE;
  173.     Vm_MakeUnaccessible((Address)userLockPtr, numBytes);
  174.     SyncEventWakeupInt((unsigned int)lockPtr);
  175.  
  176.     if (SyncEventWaitInt(event, wakeIfSignal)) {
  177.     status = GEN_ABORTED_BY_SIGNAL;
  178.     } else {
  179.     status = SUCCESS;
  180.     }
  181. #ifdef spur
  182.     Mach_InstCountEnd(1);
  183. #endif
  184.     MASTER_UNLOCK(sched_MutexPtr);
  185.  
  186.     (void)Vm_UnpinUserMem(sizeof(*lockPtr), (Address)lockPtr);
  187.     return(status);
  188. }
  189.  
  190.  
  191. /*
  192.  * ----------------------------------------------------------------------------
  193.  *
  194.  * Sync_SlowBroadcastStub --
  195.  *
  196.  *    Stub for the Sync_SlowBroadcast system call.
  197.  *      Mark all processes waiting on an event as runable.  The flag that
  198.  *      indicates there are waiters is cleared here inside the protected
  199.  *      critical section.  This has "broadcast" semantics because everyone
  200.  *      waiting is made runable.  We don't yet have a mechanism to wake up
  201.  *      just one waiting process.
  202.  *
  203.  * Results:
  204.  *    None.
  205.  *
  206.  * Side effects:
  207.  *    Make processes waiting on the event runnable.
  208.  *
  209.  * ----------------------------------------------------------------------------
  210.  */
  211.  
  212. ReturnStatus
  213. Sync_SlowBroadcastStub(event, waitFlagPtr)
  214.     unsigned int event;
  215.     int *waitFlagPtr;
  216. {
  217.     ReturnStatus    status;
  218.     int        *userWaitFlagPtr; /* waitFlagPtr in kernel addr space */
  219.     int        numBytes;    /* number of bytes accessible */
  220.  
  221.     status = Vm_PinUserMem(VM_READWRITE_ACCESS, sizeof(*waitFlagPtr), 
  222.             (Address)waitFlagPtr);
  223.     if (status != SUCCESS) {
  224.     return(status);
  225.     }
  226.     Vm_MakeAccessible(VM_READWRITE_ACCESS, sizeof(*waitFlagPtr),
  227.               (Address)waitFlagPtr, &numBytes,
  228.               (Address *)&userWaitFlagPtr);
  229.  
  230.     MASTER_LOCK(sched_MutexPtr);
  231.  
  232.     *userWaitFlagPtr = FALSE;
  233.     Vm_MakeUnaccessible((Address)userWaitFlagPtr, numBytes);
  234.     SyncEventWakeupInt(event);
  235.  
  236. #ifdef spur
  237.     if (Mach_InstCountIsOn(1)) {
  238.     panic("About to unlock sched_Mutex with inst count on.\n");
  239.     }
  240. #endif
  241.     MASTER_UNLOCK(sched_MutexPtr);
  242.  
  243.     (void)Vm_UnpinUserMem(sizeof(*waitFlagPtr), (Address)waitFlagPtr);
  244.  
  245.     return(SUCCESS);
  246. }
  247.